package models;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.*;

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import play.db.jpa.Model;

@Entity
@Table(name = "Virtual_Board")
public class VirtualBoard extends Model {

	public String type;

	@OneToMany(mappedBy = "board", cascade = { CascadeType.REMOVE })
	public List<BoardColumn> columns;

	@OneToOne
	public Event event;

	/**
	 * constructs a VirtualBoard
	 * 
	 * @param event
	 * @param type
	 * @param columns
	 */
	public VirtualBoard(Event event, List<BoardColumn> columns) {
		this.columns = columns;
		this.event = event;

	}

	/**
	 * this method takes as parameters the Id of an event and the type of the
	 * requested board and generates a virtual board for the associated project
	 * and save it in the DB also it calls retrieveBoard to show the board
	 * itself
	 * 
	 * @param eventId
	 *            event this board belong to
	 * @param type
	 *            type of the board
	 */
	public static boolean createBoard(Event event) {
		
		LinkedList<BoardColumn> columns = new LinkedList<BoardColumn>();
		VirtualBoard board = new VirtualBoard(event, columns);
		board.save();
		BoardColumn column;
		List status = event.project.availableTaskStatuses();
		if (status != null) {
			for (int i = 0; i < status.size(); i++) {
				column = new BoardColumn(i + 1, ((TaskStatus) (status.get(i))),
						((TaskStatus) (status.get(i))).status, board);
				column.save();
				columns.add(column);
			}
			board.columns = columns;
			board.save();
			event.board = board;
			event.save();
			
		}
		return true;
	}

	/**
	 * This Method takes as a parameter the Id of a project and deletes its
	 * boards from the DB. It is only used when the project is deleted.
	 * 
	 * @param projectId
	 *            project to delete the boards of
	 * 
	 */
	public static boolean deleteBoards(long projectId) {
		List<Event> events = ((Project) Project.findById(projectId)).events;
		if (events != null)
			for (int i = 0; i < events.size(); i++)
				if (events.get(i).board != null) {
					events.get(i).board.delete();
				}
		return true;
	}

	/**
	 * change the position of the column in the db after drag and drop on the
	 * board
	 * 
	 * @param boardID
	 *            board contains the columns
	 * @param oldClumn
	 *            The old position number of the column
	 * @param newClumn
	 *            The new position number of the column
	 * @return boolean true if succeeded to change.
	 */
	public boolean changeColumnOrder(int oldClumn, int newClumn) {
		BoardColumn c = this.columns.remove(oldClumn);
		this.columns.add(newClumn, c);
		for (int i = 0; i < this.columns.size(); i++) {
			this.columns.get(i).positionNumber = i;
			this.columns.get(i).save();
		}

		return true;
	}
	/**
	 * This method takes as a parameter a list of columns and gets a list of the
	 * statuses and the names (visual name) of this status an return a list of
	 * strings of the statuses and names
	 * 
	 * @param columns
	 *            list of columns to get their status and names
	 * @return list of status and names of these columns
	 */
	public List<TaskStatus> getStatus() {
		List<TaskStatus> result = new LinkedList<TaskStatus>();
		for (int i = 0; i < columns.size(); i++) {
			result.add(columns.get(i).status);
		}
		return result;
	}
	/**
	 * This method gets as parameters an event an a virtual board and returns
	 * the task statuses that are available for this event but not appearing on
	 * the board
	 * 
	 * @param event
	 *            event this board belong to
	 * @param board
	 *            board being designed
	 * @return list of task statuses available for this event
	 */
	public  List<TaskStatus> getStatusNotTaken() {		
		List<TaskStatus> statusNottaken = new LinkedList<TaskStatus>();
		statusNottaken.addAll( event.project.availableTaskStatuses());	
		statusNottaken.removeAll( this.getStatus() );
		return statusNottaken;
	}

}